package cn.com.css.taxInspection.system.service.impl;

import cn.com.css.taxInspection.common.constants.Constants;
import cn.com.css.taxInspection.common.constants.NumConstants;
import cn.com.css.taxInspection.common.exception.BusinessException;
import cn.com.css.taxInspection.common.exception.code.BaseResponseCode;
import cn.com.css.taxInspection.gt3.entity.DmGySwjgEntity;
import cn.com.css.taxInspection.gt3.entity.DmGySwryEntity;
import cn.com.css.taxInspection.gt3.entity.DmQxSwrysfEntity;
import cn.com.css.taxInspection.gt3.mapper.DmGySwryMapper;
import cn.com.css.taxInspection.gt3.mapper.DmQxSwrysfMapper;
import cn.com.css.taxInspection.gt3.service.DmGySwjgService;
import cn.com.css.taxInspection.gt3.service.DmQxSwrysfService;
import cn.com.css.taxInspection.system.entity.SysLog;
import cn.com.css.taxInspection.system.entity.SysLoginIdentityEntity;
import cn.com.css.taxInspection.system.entity.SysRole;
import cn.com.css.taxInspection.system.entity.SysUser;
import cn.com.css.taxInspection.system.mapper.SysLogMapper;
import cn.com.css.taxInspection.system.mapper.SysUserMapper;
import cn.com.css.taxInspection.system.service.*;
import cn.com.css.taxInspection.system.vo.req.UserRoleOperationReqVO;
import cn.com.css.taxInspection.system.vo.res.LoginRespVO;
import cn.com.css.taxInspection.system.vo.res.UserOwnRoleRespVO;
import cn.com.css.taxInspection.util.IPUtils;
import cn.com.css.taxInspection.util.PasswordUtils;
import cn.com.css.taxInspection.util.TsBqUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements UserService {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private RoleService roleService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private DmQxSwrysfMapper dmQxSwrysfMapper;
    @Resource
    private DmQxSwrysfService dmQxSwrysfService;
    @Resource
    private DmGySwjgService dmGySwjgService;
    @Resource
    private HttpSessionService httpSessionService;
    @Resource
    private SysLogMapper sysLogMapper;
    @Resource
    private SysLoginIdentityService sysLoginIdentityService;
    @Resource
    private DmGySwryMapper dmGySwryMapper;


    @Value("${spring.redisToken.allowMultipleLogin}")
    private Boolean allowMultipleLogin;


    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);


    @Override
    public void register(SysUser sysUser) {
        SysUser sysUserOne = sysUserMapper
                .selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, sysUser.getUsername()));
        if (sysUserOne != null) {
            throw new BusinessException("用户名已存在！");
        }
        sysUser.setSalt(PasswordUtils.getSalt());
        String encode = PasswordUtils.encode(sysUser.getPassword(), sysUser.getSalt());
        sysUser.setPassword(encode);
        sysUserMapper.insert(sysUser);
    }

    @Override
    @Transactional
    public LoginRespVO login(SysUser vo, HttpServletRequest request) {
        SysUser sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
        if (null == sysUser) {
            //1.根据username先查user表 查到验证密码
            //2.没查到 根据username再查swry表 查到验证密码 将用户名密码新添加usr表
            DmGySwryEntity swry = dmGySwryMapper.selectOne(Wrappers.<DmGySwryEntity>lambdaQuery().eq(DmGySwryEntity::getSwryDm, vo.getUsername()));
            if (null == swry) {
                throw new BusinessException(BaseResponseCode.NOT_ACCOUNT);
            }
            if (!vo.getPassword().equals(String.valueOf(NumConstants.ONE))){
                throw new BusinessException(BaseResponseCode.PASSWORD_ERROR);
            }
            SysUser user = new SysUser();
            user.setId(swry.getSwryDm());
            user.setUsername(swry.getSwryDm());
            user.setPhone(swry.getLxdh());
            user.setRealName(swry.getSwryxm());
            user.setNickName(swry.getSwryxm());
            user.setSex(Integer.valueOf(swry.getXbDm()));
            user.setStatus(Constants.STATUS_NORMAL);
            user.setCreateWhere(Constants.CREATE_WHERE_HXSWRYDMTB);
            user.setPassword(String.valueOf(NumConstants.ONE));
            user.setCreateWhere(Constants.CREATE_WHERE_HXSWRYDMTB);
            user.setSalt(PasswordUtils.getSalt());
            String encode = PasswordUtils.encode(user.getPassword(), user.getSalt());
            user.setPassword(encode);
            user.setCreateId(swry.getSwryDm());
            user.setDeptId(dmQxSwrysfService.getDeptIdByUserId(user.getUsername()));
            sysUserMapper.insert(user);
            sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
        }
        if (sysUser.getStatus() == 2) {
            throw new BusinessException(BaseResponseCode.USER_LOCK);
        }
        if (!PasswordUtils.matches(sysUser.getSalt(), vo.getPassword(), sysUser.getPassword())) {

            // TODO 用户锁定，当密码输入一定次数后自动锁定账户。 5次
            HttpSession session = request.getSession();
            Object attribute = session.getAttribute("USERLOCK");
            if (attribute == null) {
                request.getSession().setAttribute("USERLOCK", "1");
            } else {
                int i = Integer.parseInt(session.getAttribute("USERLOCK").toString());
                // 输入错误密码的次数
                if (i == 5) {
                    Date date = new Date();
                    sysUser.setStatus(2);
                    sysUser.setUpdateTime(date);
                    sysUserMapper.updateById(sysUser);
                } else {
                    i++;
                    request.getSession().setAttribute("USERLOCK", i);
                }
            }
            throw new BusinessException(BaseResponseCode.PASSWORD_ERROR);
        }

        // edit 增加对身份的处理
        // 先取sysLoginIdentity表身份处理
        SysLoginIdentityEntity sysLoginIdentityEntity = sysLoginIdentityService.getById(sysUser.getId());
        List<DmQxSwrysfEntity> dmQxSwrysfList = new ArrayList<>();
        if (TsBqUtils.isNotNull(sysLoginIdentityEntity)) {
            String swrysfDm = sysLoginIdentityEntity.getSwrysfDm();
            DmQxSwrysfEntity userIdentityByIdentity = dmQxSwrysfService.getUserIdentityByIdentity(swrysfDm);
            if (TsBqUtils.isNull(userIdentityByIdentity)) {
                log.debug("userIdentityByIdentity:" + userIdentityByIdentity);
                throw new BusinessException(BaseResponseCode.IDENTITY_ERROR);
            } else {
                dmQxSwrysfList.add(userIdentityByIdentity);
            }
        } else {
            dmQxSwrysfList = dmQxSwrysfService.getUserIdentityById(sysUser.getId());
            if (TsBqUtils.isNull(dmQxSwrysfList)) {
                dmQxSwrysfList = dmQxSwrysfService.getByUserId(sysUser.getId());
            }
        }
        DmQxSwrysfEntity dmQxSwrysfEntity = dmQxSwrysfList.get(0);
        sysUser.setDeptId(dmQxSwrysfEntity.getSfswjgDm());
        sysUser.setDeptNo(dmQxSwrysfEntity.getSfswjgDm());
        sysUser.setRysfmc(dmQxSwrysfEntity.getRysfmc());
        String swrysfDm = dmQxSwrysfEntity.getSwrysfDm();
        sysUser.setSwrysfDm(swrysfDm);
        LoginRespVO respVO = new LoginRespVO();
        BeanUtils.copyProperties(sysUser, respVO);
        // 是否删除之前token， 此处控制是否支持多登陆端；
        // true:允许多处登陆; false:只能单处登陆，顶掉之前登陆
        if (!allowMultipleLogin) {
            httpSessionService.abortUserById(sysUser.getId());
        }
        String token = httpSessionService.createTokenAndUser(sysUser, roleService.getRoleNames(swrysfDm), roleService.getRoleIds(swrysfDm), permissionService.getPermissionsByUserId(swrysfDm));
        respVO.setAccessToken(token);

        // TODO 记录登录
        SysLog sysLog = new SysLog();
        // 请求的方法名
        String className = "cn.com.css.taxInspection.system.controller.UserController";
        String methodName = "login";
        sysLog.setMethod(className + "." + methodName + "()");
        // 设置IP地址
        sysLog.setIp(IPUtils.getIpAddr(request));
        // 用户名
        String userId = vo.getUsername();
        String username = vo.getUsername();
        sysLog.setUsername(username);
        sysLog.setUserId(userId);
        sysLog.setOperation("用户登录");
        sysLog.setCreateTime(new Date());
        sysLog.setTaxorgcode(dmQxSwrysfEntity.getSfswjgDm());
        sysLogMapper.insert(sysLog);
        logger.info("sysLog*****************************************");
        logger.info("sysLog {}", sysLog);
        logger.info("request {}", request);
        logger.info("vo {}", vo);
        logger.info("sysLog*****************************************");
        return respVO;
    }

    @Override
    public void updateUserInfo(SysUser vo) {
        SysUser sysUser = sysUserMapper.selectById(vo.getId());
        if (null == sysUser) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        // 如果用户名变更
        if (!sysUser.getUsername().equals(vo.getUsername())) {
            SysUser sysUserOne = sysUserMapper
                    .selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
            if (sysUserOne != null) {
                throw new BusinessException("用户名已存在！");
            }
        }

        // 如果用户名、密码、状态 变更，删除redis中用户绑定的角色跟权限
        if (!sysUser.getUsername().equals(vo.getUsername())
                || (!StringUtils.isEmpty(vo.getPassword())
                && !sysUser.getPassword().equals(PasswordUtils.encode(vo.getPassword(), sysUser.getSalt())))
                || !sysUser.getStatus().equals(vo.getStatus())) {
            httpSessionService.abortUserById(vo.getId());
        }

        if (!StringUtils.isEmpty(vo.getPassword())) {
            String newPassword = PasswordUtils.encode(vo.getPassword(), sysUser.getSalt());
            vo.setPassword(newPassword);
        } else {
            vo.setPassword(null);
        }
        vo.setUpdateId(httpSessionService.getCurrentUserId());
        sysUserMapper.updateById(vo);
    }

    @Override
    public void updateUserInfoMy(SysUser vo) {
        SysUser user = sysUserMapper.selectById(httpSessionService.getCurrentUserId());
        if (null == user) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        if (!StringUtils.isEmpty(vo.getPassword())) {
            String newPassword = PasswordUtils.encode(vo.getPassword(), user.getSalt());
            vo.setPassword(newPassword);
        } else {
            vo.setPassword(null);
        }
        vo.setUpdateId(httpSessionService.getCurrentUserId());
        sysUserMapper.updateById(vo);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public IPage<DmQxSwrysfEntity> pageInfo(SysUser vo) {
        String currentDeptId = httpSessionService.getCurrentDeptId();
        String deptNo = vo.getDeptNo();
        String username = vo.getUsername();
        String nickName = vo.getNickName();
        String sjswjgDm;
        List<DmGySwjgEntity> dmGySwjgEntityList = new ArrayList<>();
        if (!TsBqUtils.isNull(deptNo)) {
            sjswjgDm = deptNo;
        } else {
            if ("12101009000".equals(currentDeptId)) {
                sjswjgDm = "12101009000";
                dmGySwjgEntityList = dmGySwjgService.selectQsSwjgById(sjswjgDm);
            } else {
                DmGySwjgEntity dmGySwjgEntity = dmGySwjgService.getById(currentDeptId);
                sjswjgDm = dmGySwjgEntity.getSjswjgDm();
                dmGySwjgEntityList = TsBqUtils.recursionLevelTaxOrg(sjswjgDm);
            }
        }
        List<String> taxOrglist = new ArrayList<>();
        taxOrglist.add(sjswjgDm);
        if (!TsBqUtils.isNull(dmGySwjgEntityList)) {
            for (DmGySwjgEntity dmGySwjg : dmGySwjgEntityList) {
                String swjgDm = dmGySwjg.getSwjgDm();
                taxOrglist.add(swjgDm);
            }
        }
        Page page = new Page(vo.getPage(), vo.getLimit());
        LambdaQueryWrapper<DmQxSwrysfEntity> queryWrapper = Wrappers.lambdaQuery();
        if (!TsBqUtils.isNull(username)) {
            queryWrapper.like(DmQxSwrysfEntity::getSwryDm, username);
        }
        if (!TsBqUtils.isNull(nickName)) {
            queryWrapper.like(DmQxSwrysfEntity::getSfswjgmc, nickName);
        }
        queryWrapper.in(DmQxSwrysfEntity::getSfswjgDm, taxOrglist);
        queryWrapper.orderByDesc(DmQxSwrysfEntity::getSwrysfDm);
        return dmQxSwrysfMapper.selectPage(page, queryWrapper);
    }

    @Override
    public SysUser getUser(String id) {
        if (StringUtils.isEmpty(id)) {
            return null;
        }
        return this.getById(id);
    }

    @Override
    public void addUser(SysUser vo) {
        SysUser sysUserOne = sysUserMapper
                .selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
        if (sysUserOne != null) {
            throw new BusinessException("用户已存在，请勿重复添加！");
        }
        vo.setSalt(PasswordUtils.getSalt());
        String encode = PasswordUtils.encode(vo.getPassword(), vo.getSalt());
        vo.setPassword(encode);
        vo.setStatus(1);
        vo.setCreateWhere(1);
        sysUserMapper.insert(vo);
        if (null != vo.getRoleIds() && !vo.getRoleIds().isEmpty()) {
            UserRoleOperationReqVO reqVO = new UserRoleOperationReqVO();
            reqVO.setUserId(vo.getId());
            reqVO.setRoleIds(vo.getRoleIds());
            userRoleService.addUserRoleInfo(reqVO);
        }
    }

    @Override
    public void updatePwd(SysUser vo) {
        SysUser sysUser = sysUserMapper.selectById(vo.getId());
        if (sysUser == null) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        if (!PasswordUtils.matches(sysUser.getSalt(), vo.getOldPwd(), sysUser.getPassword())) {
            throw new BusinessException(BaseResponseCode.OLD_PASSWORD_ERROR);
        }
        if (sysUser.getPassword().equals(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()))) {
            throw new BusinessException("新密码不能与旧密码相同");
        }
        sysUser.setPassword(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()));
        sysUserMapper.updateById(sysUser);
        httpSessionService.abortAllUserByToken();
    }

    @Override
    public UserOwnRoleRespVO getUserOwnRole(String userId) {
        List<String> roleIdsByUserId = userRoleService.getRoleIdsByUserId(userId);
        List<SysRole> list = roleService.list();
        UserOwnRoleRespVO vo = new UserOwnRoleRespVO();
        vo.setAllRole(list);
        vo.setOwnRoles(roleIdsByUserId);
        return vo;
    }

    @Override
    public void forgetPwd(SysUser vo) {
        // TODO Auto-generated method stub

    }

    @Override
    public void updateUserUnlock(SysUser sysUser) {
        // TODO Auto-generated method stub

    }

    //查询系统userID
    @Override
    public String queryCreateName(String currentUserId) {
        String createName;
        SysUser sysUser = getById(currentUserId);
        if (TsBqUtils.isNotNull(sysUser)) {
            createName = sysUser.getNickName();
        } else {
            createName = currentUserId;
        }
        return createName;
    }

    public SysUser getById(String id) {
        if (StringUtils.isEmpty(id)) {
            return null;
        }
        // 查询用户的逻辑
        return sysUserMapper.selectById(id);
    }

}
